#include "OutputLog.h"
#include "FSMC_SRAM.h"
#include "print_rtt.h"
#include <stdarg.h>
#include <string.h>

// 1. 定义一个 StaticSemaphore_t 类型的变量，用于存储互斥量状态。
//    定义为全局变量，确保其生命周期贯穿整个程序。
StaticSemaphore_t xLogOutMutexBuffer;

// 互斥量句柄，用于访问互斥量。
SemaphoreHandle_t xLogOutMutex;

char *log_data_into_queue = (char *)LOG_PUSH_DATA_BEG_ADDR;

QueueHandle_t xLogQueue;

// 4. 定义用于静态队列的内存
static char *ucQueueStorageArea = (char *)LOG_OUTPUT_QUEUE_BEG_ADDR;

static StaticQueue_t xQueueBuffer;

uint8_t g_log_status = 0;
unsigned char g_debug_threshold;
unsigned char ELOG_OUTPUT_LVL;
char log_buffer[2048]; //= (char *)LOG_OUTPUT_IN_BEG_ADDR;
int fputc(int ch, FILE *f)
{
  //   uart_send_char((char)ch);
  return ch;
}
void output_log_uart_init(unsigned char debug_threshold)
{
#ifdef UART_LOG_OUT
  GPIO_InitTypeDef GPIO_InitStruct;
  USART_InitTypeDef USART_InitStruct;

  // 1. 使能时钟
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);  // 使能 GPIOB 时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能 USART1 时钟

  // 2. 配置 GPIO 引脚
  // PB6 -> USART1_TX
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;      // 复用功能
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 输出速率
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;    // 推挽输出
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;      // 上拉
  GPIO_Init(GPIOB, &GPIO_InitStruct);

  // PB7 -> USART1_RX
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;     // 复用功能
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // 不上下拉
  GPIO_Init(GPIOB, &GPIO_InitStruct);

  // 将 PB6 和 PB7 连接到 USART1 (AF7)
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

  // 3. 配置 USART1
  USART_InitStruct.USART_BaudRate = 115200;
  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
  USART_InitStruct.USART_StopBits = USART_StopBits_1;
  USART_InitStruct.USART_Parity = USART_Parity_No;
  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 同时使能发送和接收
  USART_Init(USART1, &USART_InitStruct);

  // 使能 USART1
  USART_Cmd(USART1, ENABLE);

#endif
  g_debug_threshold = debug_threshold;
  ELOG_OUTPUT_LVL = debug_threshold;
}
void debug_message_out(unsigned char level, const char *file, int line, const char *func, const char *format, ...)
{
#ifdef UART_LOG_OUT
  va_list argp;
  char str[128];
  if ((unsigned char)level > (unsigned char)g_debug_threshold)
  {
    return;
  }
  va_start(argp, format);
  vsprintf(str, format, argp);
  va_end(argp);
  printf("%s:%d:%s:%s\n", file, line, func, str);
#endif
  return;
}
void uart_send_char(char c)
{
  // ... 你的串口发送代码 ...
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
    ;
  USART_SendData(USART1, (uint16_t)c);
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
    ;
}
void uart_send_string(const char *str)
{
  while (*str)
  {
    uart_send_char(*str++);
  }
}
void mutx_init_and_set_threshold(unsigned char level)
{
  xLogOutMutex = xSemaphoreCreateMutexStatic(&xLogOutMutexBuffer);
  ELOG_OUTPUT_LVL = level;

  if (xLogOutMutex == NULL)
  {
		LOG_ERROR("Failed to create xLogOutMutex\n");
    return;
  }
  g_log_status = 1;
  LOG_I("create xLogOutMutx success!\r\n");
  xLogQueue = xQueueCreateStatic(
      8,
      1024,
      (uint8_t *)ucQueueStorageArea,
      &xQueueBuffer);
}
void set_threshold(unsigned char level)
{
  ELOG_OUTPUT_LVL = level;
}

void message_out(unsigned char level, const char *file, int line, const char *func, const char *format, ...)
{
  va_list args;
  va_start(args, format);

  // 1. (可选) 将日志级别转换为字符串
  const char *level_str[] = {"ASSERT", "ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"};
  if (level >= sizeof(level_str) / sizeof(level_str[0]))
  {
    level = 0; // 默认级别
  }
  int written_bytes = 0;
  // 2. (可选) 从完整路径中提取文件名
  const char *filename = file;
  const char *last_slash = strrchr(file, '/');
  const char *last_backslash = strrchr(file, '\\');
  if (last_slash != NULL)
  {
    filename = last_slash + 1;
  }
  else if (last_backslash != NULL)
  {
    filename = last_backslash + 1;
  }

  // 3. 格式化日志头部和内容到同一个缓冲区
  //    a. 先格式化头部
  written_bytes += snprintf(log_buffer + written_bytes, sizeof(log_buffer) - written_bytes,
                            "%s [%s:%d] [%s] ",
                            level_str[level], filename, line, func);

  //    b. 再格式化日志内容 (使用 vsnprintf)
  written_bytes += vsnprintf(log_buffer + written_bytes, sizeof(log_buffer) - written_bytes,
                             format, args);
  va_end(args);
  //4. 输出
  switch (g_log_status)
  {
  case 0:
    /* code */
    uart_send_string(log_buffer);
    break;
  case 1: //调度开始了。
    if (xSemaphoreTake(xLogOutMutex, portMAX_DELAY) == pdPASS)
    {
      uart_send_string(log_buffer);
      xSemaphoreGive(xLogOutMutex);
    }
    break;
  case 2: //线程准备好了。
    memcpy(log_data_into_queue, log_buffer, written_bytes);
    xQueueSend(xLogQueue, log_data_into_queue, portMAX_DELAY);
    break;
  default:

    break;
  }
}
